package com.rockcent.third.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rockcent.common.common.JsonResult;
import com.rockcent.common.common.RestDoing;
import com.rockcent.common.controller.BaseController;
import com.rockcent.common.utils.RequestUtils;
import com.rockcent.mall.lib.domain.*;
import com.rockcent.mall.lib.domain.enumclass.*;
import com.rockcent.mall.lib.dto.MallDto;
import com.rockcent.mall.lib.dto.UserInfoDto;
import com.rockcent.mall.lib.repository.*;
import com.rockcent.third.Prop;
import com.rockcent.third.Routes;
import com.rockcent.third.helper.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.Date;
import java.time.Instant;
import java.util.*;

/**
 * Created by zhangjh on 2016/12/20.
 */
@RestController
public class SSOController extends BaseController {

    private final Logger log = LoggerFactory.getLogger(SSOController.class);

    @Autowired
    private UserHelper userHelper;
    @Autowired
    private CaptchaHelper captchaHelper;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private Validator validator;

    @Autowired
    private MallFundRepository mallFundRepository;

    @Autowired
    private UserInfoRepository userInfoRepository;
    @Autowired
    private SysUserRoleRepository sysUserRoleRepository;
    @Autowired
    private SysPermissionRepository sysPermissionRepository;


    @Autowired
    private UploadFileRepository uploadFileRepository;

    @Autowired
    private CertifyConfigRepository certifyConfigRepository;

    @Autowired
    private CateTemplateRepository cateTemplateRepository;
    @Autowired
    private CategoryRepository categoryRepository;

    @Autowired
    private Routes routes;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private Prop prop;
    @Autowired
    private MerchantRepository merchantRepository;
    @Autowired
    private MallRepository mallRepository;

    @Autowired
    private CodeHelper codeHelper;

    @Autowired
    private MallCertifyConfigsRepository mallCertifyConfigsRepository;
    @Autowired
    private SysRolePermissionRepository sysRolePermissionRepository;

    /**
     * @api {post} /sso/user/login 用户登录接口
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiHeader {String} content-type <code>必须参数</code> 请求content-type
     *
     * @apiParam {String} username <code>必须参数</code> 用户名
     * @apiParam {String} password <code>必须参数</code> 密码
     *
     * @apiSuccess {List} setCookieCustomerDomainList 需要设置cookie的域名
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": {
     *      "id": 545,
     *      "username": "13450286811",
     *
     *      "permissionList": [
     *           {
     *               "mallName": "测试公司",
     *               "mallLogoPath": null,
     *               "merchantUrl": "http://beta.b.dev.rockcent.com/business",
     *               "mallUrl": "http://beta.b.dev.rockcent.com/mall"
     *           }
     *      ],
     *      "userToken": "07835bbfa03d2133348ff5a996a1cc2e",
     *      "setCookieCustomerDomainList": [
     *          "test.com",
     *          "sifangstreet.com"
     *      ]
     *  }
     * }
     * @apiErrorExample {json} 101
     * {
     *  "code":"101",
     *  "desc":"用户名不存在"
     * }
     * @apiErrorExample {json} 102
     * {
     *  "code":"102",
     *  "desc":"用户状态异常"
     * }
     * @apiErrorExample {json} 103
     * {
     *  "code":"103",
     *  "desc":"密码错误"
     * }
     *
     */
    @RequestMapping(value = Routes.SSO_USER_LOGIN, method = RequestMethod.POST)
    public JsonResult userLogin(@RequestBody UserInfoDto userInfoDto, HttpServletRequest request, HttpServletResponse response) {
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(userInfoDto.username)) {
                jsonResult.remind(UserInfo.CHECK_USERNAME_IS_NOT_NULL, log);
                return;
            }
            if (StringUtils.isBlank(userInfoDto.password)) {
                jsonResult.remind(UserInfo.CHECK_PASSWORD_IS_NOT_NULL, log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(userInfoDto.username);
            if (userInfo == null) {
                jsonResult.saveResult(JsonResult.CD_101, UserInfo.REMIND_USERNAME_IS_NOT_EXIST, log);//前端要求自定义CODE,用户不存在
                return;
            }
            // 邮箱注册没有激活
            if (UserInfoStatus.INACTIVE.equals(userInfo.getStatus())) {
                jsonResult.saveResult(JsonResult.CD_102,UserInfo.REMIND_STATUS_EXCEPTION, log);//前端要求自定义CODE 用户未激活
                return;
            }
            if (!UserInfoStatus.ACTIVE.equals(userInfo.getStatus())) {
                jsonResult.saveResult(JsonResult.CD_102,UserInfo.REMIND_STATUS_EXCEPTION, log);//前端要求自定义CODE 用户已停用或已删除
                return;
            }
            String md5Password = userHelper.getMd5Password(userInfo.getSalt(), userInfoDto.password);
            if (!md5Password.equals(userInfo.getPassword())) {
                jsonResult.saveResult(JsonResult.CD_103, UserInfo.REMIND_PASSWORD_ERROR, log);//前端要求自定义CODE 密码错误
                return;
            }
            UserInfoDto result = userHelper.setSession(userInfo, request);
            result.permissionList = userHelper.getPermissionList(result);

            List<String> setCookieCustomerDomainList = new ArrayList<>();
            result.mallMap.forEach((hostname, mallDto) -> {
                String tempDomain = RequestUtils.getFirstDomain(hostname);
                if(StringUtils.isNotEmpty(tempDomain)) {
                    if (!setCookieCustomerDomainList.contains(tempDomain) && !tempDomain.contains("rockcent.com")) {
                        setCookieCustomerDomainList.add(tempDomain);
                    }
                }
            });
            result.setCookieCustomerDomainList = setCookieCustomerDomainList;
            //检查是否是自定义登录
            UserInfoDto user = userHelper.checkCustomLogin(userInfo,request);
            if(user!=null) {
                result.setReferer(user.getReferer());//登录来源地址
                result.setCustomLogin(user.getCustomLogin());//是否是自定义登录,为Y是自定义
                result.setCustomLoginMallUrl(user.getCustomLoginMallUrl());//平台链接
                result.setCustomLoginMerchantUrl(user.getCustomLoginMerchantUrl());//商家链接
            }
            result.mallMap = null;
            result.merchantMap = null;
            result.permissionMap = null;
            jsonResult.data = result;
        };

        return doing.go(userInfoDto, null, request, objectMapper, log);
    }

    /**
     * @api {get} /sso/user/permission_list 用户可访问权限列表
     * @apiGroup sso
     * @apiVersion 1.0.0
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data":[
     *       {
     *           "mallName": "测试公司",
     *           "mallLogoPath": null,
     *           "merchantUrl": "http://beta.b.dev.rockcent.com/business",
     *           "mallUrl": "http://beta.b.dev.rockcent.com/mall"
     *       }
     *  ]
     * }
     */
    @RequestMapping(value = Routes.SSO_USER_PERMISSION_LIST, method = RequestMethod.GET)
    public JsonResult permissionList(HttpServletRequest request) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jr -> {
            jr.data = userHelper.getPermissionList(userInfoDto);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /sso/user/check_field 检查用户名是否存在
     * @apiGroup sso
     * @apiVersion 1.0.0
     * @apiDescription 目前支持字段email , mobile
     *
     * @apiParam {String} fieldName <code>必须参数</code> email , mobile 用户名
     * @apiParam {String} fieldValue <code>必须参数</code> 参数值
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @RequestMapping(value = Routes.SSO_USER_CHECK_FIELD, method = RequestMethod.GET)
    public JsonResult ajaxCheckField(String fieldValue, String fieldName, HttpServletRequest request) {
        RestDoing doing = jr -> {
            UserInfo userInfo = null;
            if (StringUtils.isEmpty(fieldName)) {
                jr.remind("fieldName" + UserInfo.VALUE_IS_NOT_NULL, log);
                return;
            }
            if (StringUtils.isNotEmpty(fieldName)) {
                if (!(UserInfo.ATTR_EMAIL.equals(fieldName) || UserInfo.ATTR_MOBILE.equals(fieldName))) {
                    jr.remind("fieldName必须为email或mobile", log);
                    return;
                }
            }
            if (StringUtils.isEmpty(fieldValue)) {
                jr.remind("fieldValue" + UserInfo.VALUE_IS_NOT_NULL, log);
                return;
            }
            userInfo = userInfoRepository.findByUsername(fieldValue);
            if (userInfo != null) {
                jr.remind(UserInfo.REMIND_USERNAME_IS_REGISTERED, log);
                return;
            }
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /sso/user/forget_password_check_field 用户忘记密码 检查用户名是否存在
     * @apiGroup sso
     * @apiVersion 1.0.0
     * @apiDescription 目前支持字段 email , mobile
     *
     * @apiParam {String} fieldName <code>必须参数</code> email , mobile 用户名
     * @apiParam {String} fieldValue <code>必须参数</code> 参数值
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @RequestMapping(value = Routes.SSO_USER_FORGOT_PASSWORD_CHECK_FIELD, method = RequestMethod.GET)
    public JsonResult forgotPasswordCheckField(String fieldValue, String fieldName, HttpServletRequest request) {
        RestDoing doing = jr -> {
            UserInfo userInfo = null;
            if (StringUtils.isEmpty(fieldName)) {
                jr.remind("fieldName" + UserInfo.VALUE_IS_NOT_NULL, log);
                return;
            }
            if (StringUtils.isNotEmpty(fieldName)) {
                if (!(UserInfo.ATTR_EMAIL.equals(fieldName) || UserInfo.ATTR_MOBILE.equals(fieldName))) {
                    jr.remind("fieldName必须为email或mobile", log);
                    return;
                }
            }
            if (StringUtils.isEmpty(fieldValue)) {
                jr.remind("fieldValue" + UserInfo.VALUE_IS_NOT_NULL, log);
                return;
            }
            userInfo = userInfoRepository.findByUsername(fieldValue);
            if (userInfo == null) {
                jr.remind(UserInfo.REMIND_USERNAME_IS_NOT_EXIST, log);
                return;
            }
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /sso/user/register_save_mobile 手机用户注册
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} username <code>必须参数</code> 用户名
     * @apiParam {String} password <code>必须参数</code> 密码
     * @apiParam {String} captcha <code>必须参数</code> 验证码
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @Transactional
    @RequestMapping(value = Routes.SSO_USER_REGISTER_SAVE_MOBILE, method = RequestMethod.POST)
    public JsonResult registerByMobile(@RequestBody UserInfoDto userInfoDto, HttpServletRequest request) {
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(userInfoDto.username)) {
                jsonResult.remind(UserInfo.CHECK_USERNAME_IS_NOT_NULL,log);
                return;
            }
            if (StringUtils.isBlank(userInfoDto.password)) {
                jsonResult.remind(UserInfo.CHECK_PASSWORD_IS_NOT_NULL,log);
                return;
            }
            if (StringUtils.isBlank(userInfoDto.captcha)) {
                jsonResult.remind(UserInfo.CHECK_REGISTER_CAPTCHA_IS_NOT_NULL,log);
                return;
            }
            String key = UserInfo.REDIS_REGISTER_MOBILE_CAPTCHA_USERNAME_PREFIX + userInfoDto.username;
            String serverCaptcha = redisTemplate.opsForValue().get(key);
            if (!userInfoDto.captcha.equals(serverCaptcha)) {
                jsonResult.remind("注册验证码错误",log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(userInfoDto.username);
            if (userInfo != null) {
                jsonResult.remind(UserInfo.REMIND_USERNAME_IS_REGISTERED,log);
                return;
            }
            String salt = String.valueOf(Date.from(Instant.now()).getTime());
            userInfo = new UserInfo();
            userInfo.setUsername(userInfoDto.username);
            userInfo.setSalt(salt);
            userInfo.setStatus(UserInfoStatus.ACTIVE);
            userInfo.setMobile(userInfoDto.username);
            userInfo.setRegisterType(UserInfoRegisterType.MOBILE);
            userInfo.setPassword(userHelper.getMd5Password(salt, userInfoDto.password));
            userInfo = userInfoRepository.save(userInfo);
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /sso/user/register_save_email 邮箱用户注册保存
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} username <code>必须参数</code> 用户名
     * @apiParam {String} password <code>必须参数</code> 密码
     * @apiParam {String} hostname <code>必须参数</code> 域名
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @Transactional
    @RequestMapping(value = Routes.SSO_USER_REGISTER_SAVE_EMAIL, method = RequestMethod.POST)
    public JsonResult registerSaveEmail(@RequestBody UserInfoDto userInfoDto, HttpServletRequest request) {
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(userInfoDto.username)) {
                jsonResult.remind(UserInfo.CHECK_USERNAME_IS_NOT_NULL,log);
                return;
            }
            if (StringUtils.isBlank(userInfoDto.password)) {
                jsonResult.remind(UserInfo.CHECK_PASSWORD_IS_NOT_NULL,log);
                return;
            }
            String hostname = userInfoDto.getHostname();
            if(!userHelper.checkHostname(hostname)) {
                jsonResult.remind("非法的域名",log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(userInfoDto.username);
            if (userInfo != null) {
                jsonResult.remind(UserInfo.REMIND_USERNAME_IS_REGISTERED,log);
                return;
            }
            String salt = String.valueOf(Date.from(Instant.now()).getTime());
            userInfo = new UserInfo();
            userInfo.setUsername(userInfoDto.username);
            userInfo.setSalt(salt);
            userInfo.setStatus(UserInfoStatus.INACTIVE);
            userInfo.setEmail(userInfoDto.username);
            userInfo.setRegisterType(UserInfoRegisterType.EMAIL);
            userInfo.setPassword(userHelper.getMd5Password(salt, userInfoDto.password));
            userInfoRepository.save(userInfo);
            //发送用户激活邮件
            userHelper.sendEmail(UserInfo.REDIS_REGISTER_EMAIL_CAPTCHA_USERNAME_PREFIX, userInfoDto.username, EmailTemplateCode.SITE_REGISTER, hostname + Routes.SSO_USER_REGISTER_EMAIL_ACTIVE);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /sso/user/reset_send_register_email 邮箱用户注册重新发邮件激活
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} username <code>必须参数</code> 用户名
     * @apiParam {String} hostname <code>必须参数</code> 域名
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @Transactional
    @RequestMapping(value = Routes.SSO_USER_RESET_SEND_REGISTER_EMAIL, method = RequestMethod.GET)
    public JsonResult resetSendRegisterEmail(String username, String hostname, HttpServletRequest request) {
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(username)) {
                jsonResult.remind(UserInfo.CHECK_USERNAME_IS_NOT_NULL,log);
                return;
            }
            if(!userHelper.checkHostname(hostname)) {
                jsonResult.remind("非法的域名",log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(username);
            if (userInfo == null) {
                jsonResult.remind(UserInfo.REMIND_USERNAME_IS_NOT_EXIST,log);
                return;
            }
            if(!UserInfoStatus.INACTIVE.equals(userInfo.getStatus())) {
                jsonResult.remind(UserInfo.REMIND_STATUS_EXCEPTION,log);
                return;
            }
            //重新发送用户激活邮件
            userHelper.sendEmail(UserInfo.REDIS_REGISTER_EMAIL_CAPTCHA_USERNAME_PREFIX, username, EmailTemplateCode.SITE_REGISTER, hostname + Routes.SSO_USER_REGISTER_EMAIL_ACTIVE);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /sso/user/register_save_email_active_do 邮箱用户注册激活
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} key <code>必须参数</code> 激活码
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @RequestMapping(value = Routes.SSO_USER_REGISTER_SAVE_EMAIL_ACTIVE_DO, method = RequestMethod.GET)
    public JsonResult registerByEmailActivityDo(String key, HttpServletRequest request) {
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(key)) {
                jsonResult.remind("key" + UserInfo.VALUE_IS_NOT_NULL, log);
                return;
            }
            String username = userHelper.verifyEmail(key, UserInfo.REDIS_REGISTER_EMAIL_CAPTCHA_USERNAME_PREFIX, true);
            if (StringUtils.isBlank(username)) {
                jsonResult.remind("key为错误码", log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(username);
            if (userInfo == null) {
                jsonResult.remind(UserInfo.REMIND_USERNAME_IS_NOT_EXIST,log);
                return;
            }
            if (UserInfoStatus.ACTIVE.equals(userInfo.getStatus())) {
                jsonResult.remind("该用户已被激活",log);
                return;
            }
            //待激活更新为激活状态
            if (!UserInfoStatus.INACTIVE.equals(userInfo.getStatus())) {
                jsonResult.remind(UserInfo.REMIND_STATUS_EXCEPTION, log);
                return;
            }
            userInfo.setStatus(UserInfoStatus.ACTIVE);
            userInfoRepository.save(userInfo);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /sso/user/forgot_password_email_active_do 邮箱用户忘记密码 验证激活码是否有效
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} key <code>必须参数</code> 激活码
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     * @apiSuccess {String} data 用户名
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": "13333"
     * }
     */
    @RequestMapping(value = Routes.SSO_USER_FORGOT_PASSWORD_EMAIL_ACTIVE_DO, method = RequestMethod.GET)
    public JsonResult forgotPasswordByEmailActivityDo(String key, HttpServletRequest request) {
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(key)) {
                jsonResult.remind("key" + UserInfo.VALUE_IS_NOT_NULL, log);
                return;
            }
            String username = userHelper.verifyEmail(key, UserInfo.REDIS_FORGOT_PASSWORD_EMAIL_CAPTCHA_USERNAME_PREFIX, true);
            if (StringUtils.isBlank(username)) {
                jsonResult.remind("key为错误码", log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(username);
            if (userInfo == null) {
                jsonResult.remind(UserInfo.REMIND_USERNAME_IS_NOT_EXIST,log);
                return;
            }
            jsonResult.data = username;
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /sso/user/forgot_password_by_email_modify 邮箱用户忘记密码 修改密码
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} username <code>必须参数</code> 用户名
     * @apiParam {String} password <code>必须参数</code> 密码
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @Transactional
    @RequestMapping(value = Routes.SSO_USER_FORGOT_PASSWORD_BY_EMAIL_MODIFY, method = RequestMethod.POST)
    public JsonResult forgotPasswordModify(@RequestBody UserInfoDto userInfoDto, HttpServletRequest request) {
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(userInfoDto.username)) {
                jsonResult.remind(UserInfo.CHECK_USERNAME_IS_NOT_NULL, log);
                return;
            }
            if (StringUtils.isBlank(userInfoDto.password)) {
                jsonResult.remind(UserInfo.CHECK_PASSWORD_IS_NOT_NULL, log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(userInfoDto.username);
            if (userInfo == null) {
                jsonResult.remind(UserInfo.REMIND_USERNAME_IS_NOT_EXIST, log);
                return;
            }
            String salt = String.valueOf(Date.from(Instant.now()).getTime());
            userInfo.setPassword(userHelper.getMd5Password(salt, userInfoDto.password));
            userInfo.setSalt(salt);
            userInfoRepository.save(userInfo);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /sso/user/register_save_mobile_captcha 手机用户获取注册短信验证码
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} mobile <code>必须参数</code> 手机号码
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     * @apiSuccess {String} data 验证码
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": "11111"
     * }
     */
    @RequestMapping(value = Routes.SSO_USER_REGISTER_SAVE_MOBILE_CAPTCHA, method = RequestMethod.GET)
    public JsonResult ajaxRegisterByMobileCaptcha(String mobile, HttpServletRequest request) {
        RestDoing doing = jr -> {
            if (StringUtils.isBlank(mobile)) {
                jr.errorParam("手机号码不能为空", log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(mobile);
            if (userInfo != null) {
                jr.remind(UserInfo.REMIND_USERNAME_IS_REGISTERED, log);
                return;
            }
            jr.data = captchaHelper.send(mobile, null, UserInfo.REDIS_REGISTER_MOBILE_CAPTCHA_USERNAME_PREFIX + mobile, 180);
        };
        return doing.go(request, log);
    }


    /**
     * 新登录 用户注册验证短信验证码
     *
     * @param mobile
     * @param request
     * @return
     */
    @RequestMapping(value = Routes.PLATFORM_USER_REGISTER_SAVE_MOBILE_VERIFY_CAPTCHA, method = RequestMethod.GET)
    public JsonResult ajaxRegisterByMobileVerifyCaptcha(String mobile, String captcha, HttpServletRequest request) {
        RestDoing doing = jr -> {

            if (StringUtils.isBlank(mobile)) {
                jr.errorParam("手机号码不能为空", log);
                return;
            }
            String key = UserInfo.REDIS_REGISTER_MOBILE_CAPTCHA_USERNAME_PREFIX + mobile;
            String serverCaptcha = redisTemplate.opsForValue().get(key);
            if (!captcha.equals(serverCaptcha)) {
                jr.remind("验证码错误", log);
                return;
            }
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /sso/user/forgot_password_email 忘记密码邮件 点击发送邮件到邮箱
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} username <code>必须参数</code> 邮箱
     * @apiParam {String} hostname <code>必须参数</code> 域名
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @RequestMapping(value = Routes.SSO_USER_FORGOT_PASSWORD_EMAIL, method = RequestMethod.GET)
    public JsonResult forgotPasswordEmail(String username, String hostname, HttpServletRequest request) {
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(username)) {
                jsonResult.remind(UserInfo.CHECK_USERNAME_IS_NOT_NULL,log);
                return;
            }
            if(!userHelper.checkHostname(hostname)) {
                jsonResult.remind("非法的域名",log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(username);
            if (userInfo == null) {
                jsonResult.remind(UserInfo.REMIND_RECORD_IS_NOT_EXIST,log);;
                return;
            }
            //发送用户忘记密码邮件
            userHelper.sendEmail(UserInfo.REDIS_FORGOT_PASSWORD_EMAIL_CAPTCHA_USERNAME_PREFIX, username, EmailTemplateCode.SITE_FORGOT_PASSWORD, hostname + Routes.SSO_USER_FORGOT_PASSWORD_EMAIL_MODIFY);
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /sso/user/forgot_password_mobile 手机用户忘记密码 修改密码
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} username <code>必须参数</code> 用户名
     * @apiParam {String} password <code>必须参数</code> 密码
     * @apiParam {String} captcha <code>必须参数</code> 验证码
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @Transactional
    @RequestMapping(value = Routes.SSO_USER_FORGOT_PASSWORD_MOBILE, method = RequestMethod.POST)
    public JsonResult forgotPasswordMobile(@RequestBody UserInfoDto userInfoDto, HttpServletRequest request) {
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(userInfoDto.username)) {
                jsonResult.remind(UserInfo.CHECK_USERNAME_IS_NOT_NULL, log);
                return;
            }
            if (StringUtils.isBlank(userInfoDto.password)) {
                jsonResult.remind(UserInfo.CHECK_PASSWORD_IS_NOT_NULL, log);
                return;
            }
            if (StringUtils.isBlank(userInfoDto.captcha)) {
                jsonResult.remind(UserInfo.CHECK_REGISTER_CAPTCHA_IS_NOT_NULL, log);
                return;
            }
            String serverCaptcha = redisTemplate.opsForValue().get(UserInfo.REDIS_FORGOT_PASSWORD_MOBILE_CAPTCHA_USERNAME_PREFIX + userInfoDto.username);
            if (!userInfoDto.captcha.equals(serverCaptcha)) {
                jsonResult.remind("注册验证码错误", log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(userInfoDto.username);
            if (userInfo == null) {
                jsonResult.remind(UserInfo.REMIND_USERNAME_IS_NOT_EXIST, log);
                return;
            }
            String salt = String.valueOf(Date.from(Instant.now()).getTime());
            userInfo.setPassword(userHelper.getMd5Password(salt, userInfoDto.password));
            userInfo.setSalt(salt);
            userInfoRepository.save(userInfo);
            redisTemplate.delete(UserInfo.REDIS_FORGOT_PASSWORD_MOBILE_CAPTCHA_USERNAME_PREFIX + userInfoDto.username);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /sso/user/forgot_password_mobile_captcha 手机用户忘记密码获取短信验证码
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} mobile <code>必须参数</code> 手机号码
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     * @apiSuccess {String} data 验证码
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": "11111"
     * }
     */
    @RequestMapping(value = Routes.SSO_USER_FORGOT_PASSWORD_MOBILE_CAPTCHA, method = RequestMethod.GET)
    public JsonResult forgotPasswordMobileCaptcha(String mobile, HttpServletRequest request) {
        RestDoing doing = ret -> {
            if (StringUtils.isBlank(mobile)) {
                ret.errorParam("手机号码不能为空", log);
                return;
            }
            UserInfo userInfo = userInfoRepository.findByUsername(mobile);
            if (userInfo == null) {
                ret.remind(UserInfo.REMIND_USERNAME_IS_NOT_EXIST, log);
                return;
            }
            ret.data = captchaHelper.send(mobile, null, UserInfo.REDIS_FORGOT_PASSWORD_MOBILE_CAPTCHA_USERNAME_PREFIX + mobile, 180);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} sso/user/query_mall_by_host 根据域名读取平台图片信息
     * @apiGroup sso
     * @apiVersion 1.0.0
     *
     * @apiParam {String} host <code>必须参数</code> 域名
     *
     * @apiSuccess {String} code 返回CODE
     * @apiSuccess {String} desc 信息说明
     * @apiSuccess {String} backgroundPicture 广告图
     * @apiSuccess {String} logoBigPicture LOGO大图
     * @apiSuccess {String} logoSmallPicture LOGO小图
     * @apiSuccess {String} serviceTelephone 客服电话
     * @apiSuccess {String} onlineQq 在线QQ
     * @apiSuccess {String} icpNumber ICP备案号
     * @apiSuccess {String} tag 标签
     * @apiSuccess {String} name 平台名称
     * @apiSuccess {String} introduce 平台介绍
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *   "code": "1",
     *   "desc": "成功",
     *   "data": {
     *     "backgroundPicture": "http://uploads.rockcent.com//uat/product/face/201612/7171618218161472ac-d745-42e8-9c78-6d76499bf501u=2586659993,2540782218&fm=116&gp=0.jpg",
     *     "logoBigPicture": "http://uploads.rockcent.com//uat/product/face/201612/3019225110271dde630-1d33-4121-b2e2-7aa060aa0e2eu=424377424,1640540580&fm=116&gp=0.jpg",
     *     "logoSmallPicture": "http://uploads.rockcent.com//uat/product/face/201612/301923272956428cc46-7c7e-4d07-bc09-9fe884e0f538u=1817973948,1865687586&fm=23&gp=0.jpg"
     *   }
     * }
     */
    @RequestMapping(value = Routes.SSO_USER_QUERY_MALL_BY_HOST, method = RequestMethod.GET)
    public JsonResult queryMallByHost(String host, HttpServletRequest request) {
        RestDoing doing = ret -> {
            if (StringUtils.isBlank(host)) {
                ret.errorParam("参数不能为空", log);
                return;
            }
            MallDto dto = new MallDto();
            dto.setBackgroundPicture("");
            dto.setLogoBigPicture("");
            dto.setLogoSmallPicture("");
            dto.setIcpNumber("");
            dto.setOnlineQq("");
            dto.setServiceTelephone("");
            dto.setName("");
            dto.setTag("");
            dto.setIntroduce("");
            Mall mall = mallRepository.findByHostnameOrCustomerPlatformDomain(host);
            if(mall != null) {
                dto.setBackgroundPicture(mall.getBackgroundPicture());
                dto.setLogoBigPicture(mall.getLogoBigPicture());
                dto.setLogoSmallPicture(mall.getLogoSmallPicture());
                dto.setIcpNumber(mall.getIcpNumber());
                dto.setOnlineQq(mall.getOnlineQq());
                dto.setServiceTelephone(mall.getServiceTelephone());
                dto.setName(mall.getName());
                dto.setTag(mall.getTag());
                dto.setIntroduce(mall.getIntroduce());
            }
            ret.data = dto;
        };
        return doing.go(request, log);
    }
}
